#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
# File Name: string.sh
# Author: GID5564
# Description: functions for string
# Created Time: 07/11/23-19:37:13
#※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
#! /usr/bin/env bash


# 避免重复导入
#[[ -n $__XLIB_IMPORTED__STRING ]] && return 0
#__XLIB_IMPORTED__STRING=1

function __string_init__() {
    wait
}

function spec_char(){
    [[ -z "$1" ]] && {
        error "Usage: spec_char <特殊字符>"
        return $INVALID_ARGUMENTS
    }

    #输出特殊字符
    #\a：ALERT/BELL (从系统喇叭送出铃声)
    #\b：BACKSPACE ，也就是向左删除键
    #\c：取消行末之换行符号
    #\E：ESCAPE，跳脱键
    #\f：FORMFEED，换页字符
    #\n：NEWLINE，换行字符
    #\r：RETURN，回车键
    #\t：TAB，表格跳位键
    #\v：VERTICAL TAB，垂直表格跳位键
    #：ASCII 八进位编码(以 x 开首为十六进制) ：反斜线本身
    printf "$@" 
}

########################################
# 功能：将字符串中的特殊字符进行转义
# 参数：$1 要转义的字符串
# 返回值：转义后的字符串
# 测试:
#    original_str='This is a "test" string with special characters: $ \" \' \` ! @ # % ( ) [ ] { } < >'
#    escaped_str=$(escape_special_chars "$original_str")
#    echo "Original string: $original_str"
#    echo "Escaped string: $escaped_str"

#    这个例子中，`escape_special_chars()`函数接收一个字符串作为参数，并使用Shell中的变量替换功能，将字符串中的特殊字符进行转义。然后，我们使用`echo`输出转义后的字符串，进行验证。输出结果如下：

#   Original string: This is a "test" string with special characters: $ " ' ` ! @ # % ( ) [ ] { } <
#   Escaped string: This is a \"test\" string with special characters: \$ \" \' \` \! \@ \# \% \( \) \[ \] \{ \} \>
########################################
function transf() {
    [[ -z "$1" ]] && {
        error "Usage: transf <字符串>"
        return $INVALID_ARGUMENTS
    }

    local str="$1"
    # 将特殊字符进行转义
    str=${str//\\/\\\\}      # 反斜杠
    str=${str//\"/\\\"}      # 双引号
    str=${str//\'/\\\'}      # 单引号
    str=${str//\`/\\\`}      # 反引号
    str=${str//\$/\\\$}      # 美元符号
    str=${str//\!/\\\!}      # 感叹号
    str=${str//\@/\\\@}      # at符号
    str=${str//\#/\\\#}      # 井号
    str=${str//\%/\\\%}      # 百分号
    str=${str//\(/\\\()}     # 左括号
    str=${str//\)/\\\)}     # 右括号
    str=${str//\[/\\[}       # 左方括号
    str=${str//\]/\\]}       # 右方括号
    str=${str//\{/\\{}       # 左花括号
    str=${str//\}/\\}}       # 右花括号
    str=${str//\>/\\>}       # 大于号
    str=${str//\</\\<}       # 小于号

    echo "$str"
    unset str
}

function add_spec1(){
    [[ -z "$1" ]] && {
        error "Usage: add_spec <字符串> [字符]"
        return $INVALID_ARGUMENTS
    }

    local input=$1
    local SPEC=${2}
    local output
    local i
    local char
    if [[ -z ${SPEC} ]];then 
        SPEC='\'
    fi
    for ((i=0;i<=${#input};i++))
    do
        char=${input:$i:1}
        if [[ ${char} =~ [\@\^\$\#\*\+\.\/\|\%\&\-\~\'\"\`\ \;\:\_\!] ]];then
            output+="${SPEC}${char}"
        else
            output+="${char}"
        fi
    done
    echo ${output}
    unset input
    unset SPEC
    unset output
    unset i
    unset char
}
#优化的
function add_spec(){
    [[ -z "$1" ]] && {
        echo "Usage: add_spec <字符串> [字符]"
        return 1
    }

    local input=$1
    local SPEC=${2:-\\}
    local output=""
    local char

    for ((i=0; i<${#input}; i++)); do
        char=${input:$i:1}
        if [[ ${char} =~ [\@\^\$\#\*\+\.\/\|\%\&\-\~\'\"\`\ \;\:\_\!] ]]; then
            output+=$(printf "%s%s" "${SPEC}" "${char}")
        else
            output+="${char}"
        fi
    done

    echo "${output}"
}

########################################
# 描述: 通过时间获取随机数
# 参数: $1,$2:数字范围
# 返回: 
# 实例: rand 1 100
########################################
function rand(){  
    [[ -z "$1" || -z "$2" ]] && {
        error "Usage: rand <m> <n>"
        return $INVALID_ARGUMENTS
    }
    [[ "$1" =~ '^[0-9]+$' && "$2" =~ '^[0-9]+$' ]] && {
        local min=$1  
        local max=$(($2-$min+1))  
        local num=$(date +%s%N)  
        local rnd=$(($num%$max+$min))  
        echo ${rnd}
        unset min
        unset max
        unset num
        unset rnd
    } || {
        error "参数类型错误，此为整数类型!"
        return $INVALID_RGUMENTS  
    }
}  
########################################
# 描述: 识别字符串中汉字并返回
# 参数: $1,文本字符串
# 返回: 有汉字不为空
# 实例: get_HZ "nnm测gh试df字u符dd串"
########################################
function get_HZ(){
    [[ -z "$1" ]] && {
        error "Usage: get_HZ <字符串>"
        return $INVALID_ARGUMENTS
    }

    local str=""
    local i
    for ((i=0;i<=${#1}-1;i++))
    do
        local char=${1:$i:1}
        local tags=$(IsHZ "${char}")
        if [[ ${tags} -eq 1 ]];then
            str=${str}${char}
        fi
        unset char
        unset tags
    done
    echo ${str}
    unset i
    unset str
}
########################################
# 描述: 计算字符串中汉字个数
# 参数: $1,字符串
# 返回: 汉字个数
# 实例: get_HZ_len "nnm测gh试df字u符dd串"
########################################
function get_HZ_len(){
    [[ -z "$1" ]] && {
        error "Usage: get_HZ_len <字符串>"
        return $INVALID_ARGUMENTS
    }

    local cc=0
    local i
    for ((i=0;i<=${#1}-1;i++))
    do
        local char=${1:$i:1}
        local tags=$(IsHZ "${char}")
        if [[ ${tags} -eq 1 ]];then
            let cc++
        fi
        unset char
        unset tags
    done
    echo ${cc}
    unset i
    unset cc
}


# 判断字符是否为空
# isBlank <string>
# s="ddd"; if string::isBalnk $s; then ...
function IsBlank() {
    [[ -z "$1" ]] && {
        error "Usage: IsBlank <字符串>"
        return $INVALID_ARGUMENTS
    }

    local length=$(length "$1")
    if [[ $length -gt 0 ]]; then
        echo 1
    else
        echo 0
    fi
    unset length
}


# 判断字符串 s1 是否包含 s2
# contains <s1> <s2>
function contains() {
    [[ -z "$1" ]] && {
        error "Usage: contains <字符串> <字符串>"
        return $INVALID_ARGUMENTS
    }

    if [[ $1 =~ "$2" ]]; then
        echo 1
    else
        echo 0
    fi
}


# 转小写
function lower() {
    [[ -z "$1" ]] && {
        error "Usage: lower <字符串>"
        return $INVALID_ARGUMENTS
    }
    echo -n "$1" | awk '{print tolower($0)}'
}
to_lower() {
    echo "$1" | tr '[:upper:]' '[:lower:]'
}



# 转大写
function upper() {
    [[ -z "$1" ]] && {
        error "Usage: upper <字符串>"
        return $INVALID_ARGUMENTS
    }
    echo -n "$1" | awk '{print toupper($0)}'
}
to_upper() {
    echo "$1" | tr '[:lower:]' '[:upper:]'
}


# 串长
function length() {
    [[ -z "$1" ]] && {
        error "Usage: length <字符串>"
        return $INVALID_ARGUMENTS
    }

    echo -n "$1" | awk '{print length($0)}'
}

#按分隔符拆分字符串为数组
function split() {
    [[ -z "$1" ]] && {
        error "Usage: split <string> <delimiter>"
        return $INVALID_ARGUMENTS
    }

   IFS=$'\n' read -d "" -ra arr <<< "${1//$2/$'\n'}"
   printf '%s' "${arr[@]}"
}


# 分割字符串
# substr <string> <start index> [end index]
# substr "hello world" 1 -> ello wolrd: from 1 to end
# substr "hello world" 1 3 -> ell: from 1 to 3
function substr() {
    [[ -z "$1" ]] && {
        error "Usage: substr <string> [start] [end]"
        return $INVALID_ARGUMENTS
    }

    local s="$1"
    local start=${2-0}
    local end=${3-${#s}}
    
    [[ "$start" =~ '^[0-9]+$' && "$end" =~ '^[0-9]+$' ]] && {
    
        if [[ $3 -gt ${#s} ]];then
            end=${#s}
        fi
        echo "${s:$start:$end}"
    } || {
        error "参数类型错误!"
        return $INVALID_RGUMENTS  
    }
}


# 向字符串中的指定位置插入字符串
# 使用： v="abba"; insert v 2 "cc"; v->"abccba"
function insert() {
    [[ -z "$1" ]] && {
        error "Usage: insert <string> <index> [substr|char]"
        return $INVALID_ARGUMENTS
    }

    local src="$1"
    local position="$2"
    local val="${3:-}"
    [[ "$position" =~ '^[0-9]+$' ]] && {
        echo "${src:0:$position}${val}${src:$position}"
    }
    unset sre
    unset position
    unset val
}

# strip "The Quick Brown Fox" "[aeiou]" -> Th Qck Brwn Fx
# strip "The Quick Brown Fox" "[[:space:]]" -> TheQuickBrownFox
# strip "The Quick Brown Fox" "Quick " -> The Brown Fox
function strip() {
    [[ -z "$1" ]] && {
        error "Usage: strip <string> <pattern>"
        return $INVALID_ARGUMENTS
    }
    printf '%s' "${1//$2/}"
}

# 删除第一次出现的pattern
function lstrip() {
    [[ -z "$1" ]] && {
        error "Usage: lstrip <string> <pattern>"
        return $INVALID_ARGUMENTS
    }
    printf '%s' "${1##$2}"
}

# 删除最后出现的pattern
function rstrip() {
    [[ -z "$1" ]] && {
        error "Usage: rstrip <string> <pattern>"
        return $INVALID_ARGUMENTS
    }
    printf '%s' "${1%%$2}"
}


# 仅去除字符串两头的空格
# trim "$d" 注意双引号括起来！
function trim1() {
    [[ -z "$1" ]] && {
        error "Usage: trim <string>"
        return $INVALID_ARGUMENTS
    }

    # 去除头部空格
    local var="${1#"${1%%[![:space:]]*}"}"

    # 去除尾部空格
    echo "${var%"${var##*[![:space:]]}"}"
}

trim() {
    echo "${1}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}


# 去除头部空格
function ltrim(){
    [[ -z "$1" ]] && {
        error "Usage: ltrim <string>"
        return $INVALID_ARGUMENTS
    }

    echo "${1#"${1%%[![:space:]]*}"}"
}

# 去除尾部空格
function rtrim(){
    [[ -z "$1" ]] && {
        error "Usage: rtrim <string>"
        return $INVALID_ARGUMENTS
    }

    echo "${1#"${1##*[![:space:]]}"}"
}

# 移除所有空格，包括中间的空格在内
function atrim() {
    [[ -z "$1" ]] && {
        error "Usage: atrim <string>"
        return $INVALID_ARGUMENTS
    }

    local var="$*"
    echo "${var// /}"
}
#去除字符串中空格
function trim() {
    [[ -z "$1" ]] && {
        error "Usage: trim <string>"
        return $INVALID_ARGUMENTS
    }

    set -f
    # shellcheck disable=2048,2086
    set -- $*
    printf '%s\n' "${*//[[:space:]]/}"
    set +f
}

#从字符串中删除引号
function qtrim() {
    [[ -z "$1" ]] && {
        error "Usage: qtrim <string>"
        return $INVALID_ARGUMENTS
    }
    : "${1//\'/}"
    printf '%s' "${_//\"/}"
}

#删除所有前导/尾随空行。
function btrim() {
    [[ -z "$1" ]] && {
        error "Usage: btrim <string>"
        return $INVALID_ARGUMENTS
    }

    sed ':a;$!{N;ba;};s/^[[:space:]]*\n//;s/\n[[:space:]]*$//'
}


# 对string使用正则
# Trim leading white-space.
# regex '    hello' '^\s*(.*)'
#hello
#
## Validate a hex color.
#regex "#FFFFFF" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
##FFFFFF
#
## Validate a hex color (invalid).
#regex "red" '^(#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3}))$'
## no output (invalid)
function regx() {
    [[ -z "$1" ]] && {
        error "Usage: regx <string> <reg>"
        return $INVALID_ARGUMENTS
    }

    [[ $1 =~ $2 ]] && printf '%s' "${1}"
}

# 是否以 $2 开头
function startWith() {
    [[ -z "$1" ]] && {
        error "Usage: startWith <str> <substr>"
        return $INVALID_ARGUMENTS
    }

    local t=$(echo "$1" | \grep "^$2")
    if [[ -n $t ]]; then
        echo 1
    else
        echo 0
    fi
    unset t
}

# 是否以 $2 结尾
function endWith() {
    [[ -z "$1" ]] && {
        error "Usage: endWith <str> <substr>"
        return $INVALID_ARGUMENTS
    }

    local t=$(echo "$1" | \grep -- "$2\$")
    if [[ -n $t ]]; then
        echo 1
    else
        echo 0
    fi
    unset t
}

#四则运算
function _math() {
    [[ -z "$@" ]] && {
        error "Usage: _math <算式>"
        return $INVALID_ARGUMENTS
    }

    local _m_opts="$@"
    printf "%s" "$(($_m_opts))"
    unset _m_opts
}

function char2dec() {
    declare -A CHAR2DEC=(
        [a]=10
        [A]=10
        [b]=11
        [B]=11
        [c]=12
        [C]=12
        [d]=13
        [D]=13
        [e]=14
        [E]=14
        [f]=15
        [F]=15
    )

    [[ -z "$1" ]] && {
        error "Usage: char2dec <char>"
        return $INVALID_ARGUMENTS
    }

    local _ch=$1
    printf "%s" "${CHAR2DEC[$_ch]:-$_ch}"
    unset CHAR2DEC
}

# 把字符转换为ASCII码值
function ord() {
    [[ -z "$1" ]] && {
        error "Usage: ord <char>"
        return $INVALID_ARGUMENTS
    }
    [[ $# -ne 1 ]] && {
        error "Usage: ord <char>"
        return $INVALID_ARGUMENTS
    }
    [[ ${#1} -ne 1 ]] && {
        error "Usage: ord <char>,<char> must be a single character!"
        return $INVALID_ARGUMENTS
    }
    printf '%d' "'$1"
}

# 字符串转为十六进制串，如"Hello" -> "48 65 6c 6c 6f"
function ascii2hex() {
    [[ -z "$1" ]] && {
        error "Usage: ascii2hex <str>"
        return $INVALID_ARGUMENTS
    }

    local str="$1"
    for (( i=0; i<${#str}; i++ )); do
        printf " %02x" "'${str:i:1}"
    done
}

# 打印ascii图标
function icon() {
    declare -A ICONS=(
        [check]='\xE2\x9C\x93'
        [checkmark]='\xE2\x9C\x93'
        [X]='\xE2\x9C\x98'
        [x]='\xE2\x9C\x98'
        [xmark]='\xE2\x9C\x98'
        ['<3']='\xE2\x9D\xA4'
        [heart]='\xE2\x9D\xA4'
        [sun]='\xE2\x98\x80'
        ['*']='\xE2\x98\x85'
        [star]='\xE2\x98\x85'
        [darkstar]='\xE2\x98\x86'
        [umbrella]='\xE2\x98\x82'
        [flag]='\xE2\x9A\x91'
        [snow]='\xE2\x9D\x84'
        [snowflake]='\xE2\x9D\x84'
        [music]='\xE2\x99\xAB'
        [scissors]='\xE2\x9C\x82'
        [tm]='\xE2\x84\xA2'
        [trademark]='\xE2\x84\xA2'
        [copyright]='\xC2\xA9'
        [apple]='\xEF\xA3\xBF'
        [skull]='\xE2\x98\xA0'
        [bones]='\xE2\x98\xA0'
        [':-)']='\xE2\x98\xBA'
        [':)']='\xE2\x98\xBA'
        [smile]='\xE2\x98\xBA'
        [face]='\xE2\x98\xBA'
        [thumbsup]='\xF0\x9F\x91\x8D'
        [thumbsdown]='\xF0\x9F\x91\x8E'
        [sunglasses]='\xF0\x9F\x98\x8E'
        [cryingface]='\xF0\x9F\x98\xA2'
        [laughingface]='\xF0\x9F\x98\x82'
        [rollingeyes]='\xF0\x9F\x99\x84'
        [medicalmask]='\xF0\x9F\x98\xB7'
        [nerdface]='\xF0\x9F\xA4\x93'
        [rocket]='\xF0\x9F\x9A\x80'
        [airplane]='\xE2\x9C\x88'
        [envelope]='\xE2\x9C\x89'
        [pencil]='\xE2\x9C\x8F'
        [lock]='\xF0\x9F\x94\x92'
        [key]='\xF0\x9F\x94\x91'
        [magnifyingglass]='\xF0\x9F\x94\x8D'
        [hourglass]='\xE2\x8C\x9B'
        [calendar]='\xF0\x9F\x93\x85'
    )

    [[ -z "$1" ]] && {
        error "Usage: icon <index-string>"
        return $INVALID_ARGUMENTS
    }
    printf "${ICONS[$1]}" 
    unset ICONS
}

# 水平分割线，默认为"-"，全屏长度
# 仅重复第一个char，如需重复多个，则用 repeat
function hr() {
    [[ -z "$1" || -z "$2" ]] && {
        error "Usage: hr <字符> <数量>"
        return $INVALID_ARGUMENTS
    }
    
    local char="$1"
    local count="$2"

    local isn=$(IsNumber ${2})
    [[ ${isn} -eq 0 ]] && count=${WINDOW_COLS}
    printf "${PURPLE}%*s${RESET}\n" "${count}" '' | tr ' ' "${char}"
    unset char count isn
}

#输出指定数目的空格
function space(){
    [[ -z "$1" ]] && {
        error "Usage: space [数量]"
        return $INVALID_ARGUMENTS
    }

    local char=' '
    local count="${1}"
    local isn=$(IsNumber ${1})
    [[ ${isn} -eq 0 ]] && count=1
    printf '%*s' "${count}" '' | tr ' ' "${char}"
    unset char
    unset count
}

# 重复输出字符串
# repeat <string> [length]
# repeat $1 $2: $1=字符串，$2=重复次数
function repeat(){
    [[ -z "$1" ]] && {
        error "Usage: repeat <字符串> <重复次数>"
        return $INVALID_ARGUMENTS
    }

    local str="${1:- }"
    local num=$(($WINDOW_COLS/${#str}))
    if [[ ${#str} -gt $WINDOW_COLS ]];then
        num=1
    else
        num=$(($WINDOW_COLS/${#str}))
        #取整
        num=$(ceil $num)
    fi
    local count="${2:-${num}}"
    printf -v result "%*s" "$count" ""
    echo "${result// /$str}"
    unset str
    unset num
    unset count
    unset result
}

#小数取整
function ceil(){
    [[ -z "$1" ]] && {
        error "Usage: ceil <数字>"
        return $INVALID_ARGUMENTS
    }

  local floor=`echo "scale=0;$1/1"|bc -l ` # 向下取整
  local add=`awk -v num1=$floor -v num2=$1 'BEGIN{print(num1<num2)?"1":"0"}'`
  echo `expr $floor  + $add`
  unset floor
  unset add
  unset num1
  unset num2
}


# urlencode "https://github.com/dylanaraps/pure-bash-bible"
# -> https%3A%2F%2Fgithub.com%2Fdylanaraps%2Fpure-bash-bible
function url_encode() {
    [[ -z "$1" ]] && {
        error "Usage: url_encode <url>"
        return $INVALID_ARGUMENTS
    }

    local r i
    for ((i = 0; i < ${#1}; i++)); do
        # 截取字符串放到 $_ 终故能
        : "${1:i:1}"
        case "$_" in
        [a-zA-Z0-9.~_-])
            r+=$(printf '%s' "$_")
            ;;
        *)
            r+=$(printf '%%%02X' "'$_")
            ;;
        esac
    done
    echo "$r"
    unset r
    unset i
}
function url_decode() {
    [[ -z "$1" ]] && {
        error "Usage: url_decode <encode_str>"
        return $INVALID_ARGUMENTS
    }

    echo "$(printf '%b\n' "${1//%/\\x}")"
}

#字符串转换为数组
#方法1:
    #arrs=(`echo $str | awk -v RS=' ' '{gsub(","," "); print}'`)
#方法2
    #arrs=(`echo $str | tr $char ' '`)
#方法3
    #arrs=(`echo $str | sed 's/,/ /g'`) 
#注: 使用时用反引号``执行,如:
    #arrays=(`str_to_array $str`)
function str_to_array(){
    [[ -z "$@" ]] && {
        error "Usage: str_to_array <string> [separator]"
        return $INVALID_ARGUMENTS
    }
    local str=$1 
    local char=${2:-,}
    local arrays=()
    arrays=(`echo $str | tr $char ' '`)
    echo $arrays
    unset str char arrays
}

# 移除数组中的重复元素 "${aa[@]}"
# Usage: remove_array_dups "array"
function array_remove_duplicates() {
    [[ -z "$1" ]] && {
        error "Usage: array_remove_duplicates <array>"
        return $INVALID_ARGUMENTS
    }

    declare -A tmp_array
    for i in "$@"; do
        [[ $i ]] && IFS=" " tmp_array["${i:- }"]=1
    done

    printf '%s\n' "${!tmp_array[@]}"
    unset i
}

# 查询某元素在数组中的位置
# index "aaa" "${a[@]}"
# 返回该元素的index，不存在时则返回-1
# todo 使用nameref的版本？
function array_index() {
    [[ -z "$1" ]] && {
        error "Usage: index <element> <array>"
        return $INVALID_ARGUMENTS
    }

    local value="$1"
    shift
    local array=("$@")
    local -i index=-1
    local i
    for i in "${!array[@]}"; do
        if [[ "${array[$i]}" == "${value}" ]]; then
            local index="${i}"
        fi
    done
    echo "$index"
    if ((index == -1)); then
        return 1
    fi
    unset array
    unset index
}

# 过滤数组
function array_filter() {
    [[ -z "$1" ]] && {
        error "Usage: array_filter <pattern> <array>"
        return $INVALID_ARGUMENTS
    }

    # shellcheck disable=SC2016,SC2034
    local __doc__='
    Filters values from given array by given regular expression.

    >>> local a=(one two three wolf)
    >>> local b=( $(array::filter ".*wo.*" "${a[@]}") )
    >>> echo ${b[*]}
    two wolf
    '
    local pattern="$1"
    shift
    local array=($@)
    local element
    for element in "${array[@]}"; do
        echo "$element"
    done | \grep --extended-regexp "$pattern"
}

# 数组切片
function array_slice() {
    [[ -z "$1" ]] && {
        error "Usage: array_slice <slice> <array>"
        return $INVALID_ARGUMENTS
    }

    local __doc__='
    Returns a slice of an array (similar to Python).

    From the Python documentation:
    One way to remember how slices work is to think of the indices as pointing
    between elements, with the left edge of the first character numbered 0.
    Then the right edge of the last element of an array of length n has
    index n, for example:
    ```
    +---+---+---+---+---+---+
    | 0 | 1 | 2 | 3 | 4 | 5 |
    +---+---+---+---+---+---+
    0   1   2   3   4   5   6
    -6  -5  -4  -3  -2  -1
    ```

    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array_slice 1:-2 "${a[@]}")
    1 2 3
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(array::slice 0:1 "${a[@]}")
    0
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(Array::slice 1:1 "${a[@]}")" ] && echo empty
    empty
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(Array::slice 2:1 "${a[@]}")" ] && echo empty
    empty
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(Array::slice -2:-3 "${a[@]}")" ] && echo empty
    empty
    >>> local a=(0 1 2 3 4 5)
    >>> [ -z "$(Array::slice -2:-2 "${a[@]}")" ] && echo empty
    empty

    Slice indices have useful defaults; an omitted first index defaults to
    zero, an omitted second index defaults to the size of the string being
    sliced.
    >>> local a=(0 1 2 3 4 5)
    >>> # from the beginning to position 2 (excluded)
    >>> echo $(Array::slice 0:2 "${a[@]}")
    >>> echo $(Array::slice :2 "${a[@]}")
    0 1
    0 1

    >>> local a=(0 1 2 3 4 5)
    >>> # from position 3 (included) to the end
    >>> echo $(Array::slice 3:"${#a[@]}" "${a[@]}")
    >>> echo $(Array::slice 3: "${a[@]}")
    3 4 5
    3 4 5

    >>> local a=(0 1 2 3 4 5)
    >>> # from the second-last (included) to the end
    >>> echo $(Array::slice -2:"${#a[@]}" "${a[@]}")
    >>> echo $(Array::slice -2: "${a[@]}")
    4 5
    4 5

    >>> local a=(0 1 2 3 4 5)
    >>> echo $(Array::slice -4:-2 "${a[@]}")
    2 3

    If no range is given, it works like normal array indices.
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(Array::slice -1 "${a[@]}")
    5
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(Array::slice -2 "${a[@]}")
    4
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(Array::slice 0 "${a[@]}")
    0
    >>> local a=(0 1 2 3 4 5)
    >>> echo $(Array::slice 1 "${a[@]}")
    1
    >>> local a=(0 1 2 3 4 5)
    >>> Array::slice 6 "${a[@]}"; echo $?
    1
    >>> local a=(0 1 2 3 4 5)
    >>> Array::slice -7 "${a[@]}"; echo $?
    1
    '
    local start end array_length length
    if [[ "$1" == *:* ]]; then
        IFS=":"
        read -r start end <<<"$1"
        shift
        array_length="$#"
        # defaults
        [ -z "$end" ] && end=$array_length
        [ -z "$start" ] && start=0
        ((start < 0)) && let "start=(( array_length + start ))"
        ((end < 0)) && let "end=(( array_length + end ))"
    else
        start="$1"
        shift
        array_length="$#"
        ((start < 0)) && let "start=(( array_length + start ))"
        let "end=(( start + 1 ))"
    fi
    let "length=(( end - start ))"
    ((start < 0)) && return 1
    # check bounds
    ((length < 0)) && return 1
    ((start < 0)) && return 1
    ((start >= array_length)) && return 1
    # parameters start with $1, so add 1 to $start
    let "start=(( start + 1 ))"
    echo "${@:$start:$length}"
}

########################################
# 描述: 字符串加密/解密
# 参数: 
# 返回:$?: 0，是；1，不是
# 实例: Encry | Decry "xxx"
########################################
#加密
function encry(){
    [[ -z "$1" ]] && {
        error "Usage: encry <str>"
        return $INVALID_ARGUMENTS
    }

    local str=$1
    local ie
    local en
    
    ie=$(IsEmpty ${str})
    if [[ ${ie} -eq 1 ]];then
        #加
        #en=$(printf "%s" ${str} | base64)
        en=$(base64 <<< ${str})
        echo ${en}
    fi
    unset str
	unset ie
	unset en
}
#解密
function decry(){
    [[ -z "$1" ]] && {
        error "Usage: decry <str>"
        return $INVALID_ARGUMENTS
    }

    local str=$1
    local ie
    local de
    
    ie=$(IsEmpty ${str})
    if [[ ${ie} -eq 1 ]];then
        #解
        #de=$(printf "%s" ${str} | base64 -d) 
        de=$( base64 -d <<< ${str})
        echo ${de}
    fi
    unset str
    unset ie
    unset de
}


__string_init__










































